<!DOCTYPE html>
<html>

<head>
	<!--<script src="https://unpkg.com/@esotericsoftware/spine-canvas@4.0.*/dist/iife/spine-canvas.js"></script>-->
	<script src="../dist/iife/spine-canvas.js"></script>
</head>

<body style="margin: 0; padding: 0; background: #333">
	<canvas id="canvas" style="width: 100%; height: 100vh;"></canvas>
</body>

<script>
	let lastFrameTime = Date.now() / 1000;
	let canvas, context;
	let assetManager;
	let skeleton, animationState, bounds;
	let skeletonRenderer;

	async function load() {
		canvas = document.getElementById("canvas");
		context = canvas.getContext("2d");
		skeletonRenderer = new spine.SkeletonRenderer(context);
		skeletonRenderer.triangleRendering = true;

		// Load the assets.
		assetManager = new spine.AssetManager("/assets/");
		assetManager.loadText("spineboy-ess.json");
		assetManager.loadTextureAtlas("spineboy.atlas");
		await assetManager.loadAll();

		// Create the texture atlas and skeleton data.
		let atlas = assetManager.require("spineboy.atlas");
		let atlasLoader = new spine.AtlasAttachmentLoader(atlas);
		let skeletonJson = new spine.SkeletonJson(atlasLoader);
		let skeletonData = skeletonJson.readSkeletonData(assetManager.require("spineboy-ess.json"));

		// Instantiate a new skeleton based on the atlas and skeleton data.
		skeleton = new spine.Skeleton(skeletonData);
		skeleton.setToSetupPose();
		skeleton.updateWorldTransform(spine.Physics.update);
		bounds = skeleton.getBoundsRect();

		// Spineboy's head bounding box attachment is not attached by default. Attach it.
		skeleton.setAttachment("head-bb", "head");

		// Setup an animation state with a default mix of 0.2 seconds.
		let animationStateData = new spine.AnimationStateData(skeleton.data);
		animationStateData.defaultMix = 0.2;
		animationState = new spine.AnimationState(animationStateData);

		// Add a click listener to the canvas which checks if Spineboy's head
		// was clicked.
		canvas.addEventListener('click', event => {
			// Make the mouse click coordinates relative to the canvas.
			let canvasRect = canvas.getBoundingClientRect();
			let mouseX = event.x - canvasRect.x;
			let mouseY = event.y - canvasRect.y;

			// Create and update a SkeletonBounds instance for later hit testing.
			let skelBounds = new spine.SkeletonBounds();
			skelBounds.update(skeleton);

			// Check if the mouse coordinates are inside any of the bounding box
			// attachments of the skeleton. If so, play the jump animation, followed
			// by a looping run animation.
			if (skelBounds.containsPoint(mouseX, mouseY)) {
				let jumpEntry = animationState.setAnimation(0, "jump", false);
				let walkEntry = animationState.addAnimation(0, "run", true);
			}
		});

		requestAnimationFrame(render);
	}

	function render() {
		// Calculate the delta time between this and the last frame in seconds.
		let now = Date.now() / 1000;
		let delta = now - lastFrameTime;
		lastFrameTime = now;

		// Resize the canvas drawing buffer if the canvas CSS width and height changed
		// and clear the canvas.
		if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight) {
			canvas.width = canvas.clientWidth;
			canvas.height = canvas.clientHeight;
		}
		context.clearRect(0, 0, canvas.width, canvas.height);

		// Center the skeleton and resize it so it fits inside the canvas.
		skeleton.x = canvas.width / 2;
		skeleton.y = canvas.height - canvas.height * 0.1;
		let scale = canvas.height / bounds.height * 0.8;
		skeleton.scaleX = scale;
		skeleton.scaleY = -scale;

		// Update and apply the animation state, update the skeleton's
		// world transforms and render the skeleton.
		animationState.update(delta);
		animationState.apply(skeleton);
		skeleton.updateWorldTransform(spine.Physics.update);
		skeletonRenderer.draw(skeleton);

		requestAnimationFrame(render);
	}

	// Checks if the point given by x/y are within the circle.
	function pointInCircle(x, y, circleX, circleY, circleRadius) {
		let distX = x - circleX;
		let distY = y - circleY;
		return distX * distX + distY * distY <= circleRadius * circleRadius;
	}

	load();
</script>

</html>